import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { CreateCommentDto } from './dto/create-comment.dto';
import { UpdateCommentDto } from './dto/update-comment.dto';
import { DataSource, Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { Comment } from './entities/comment.entity';
import { User } from '../users/entities/user.entity';
import { FindAllCommentDto } from './dto/findAll-comment.dto';
import { FindOneCommentDto } from './dto/findOne-comment.dto';

@Injectable()
export class CommentsService {
  constructor(
    @InjectRepository(Comment)
    private readonly commentsRepository: Repository<Comment>,
    @InjectRepository(User)
    private readonly usersRepository: Repository<User>,
    private readonly connection: DataSource,
  ) {}

  findSelect = {
    id: true,
    like: true,
    articleId: true,
    parent: true,
    root: true,
    content: true,
    status: true,
    createTime: true,
    member: {
      id: true,
      isDeleted: true,
      username: true,
      avatarUrl: true,
      email: true,
      websiteUrl: true,
    },
  };

  async create(createCommentDto: CreateCommentDto, userId: number) {
    const user = await this.usersRepository.findOne({
      where: { id: userId, isDeleted: false },
      select: ['id', 'username', 'avatarUrl', 'websiteUrl'],
    });
    const comment = this.commentsRepository.create({
      ...createCommentDto,
      status: 1,
    });
    comment.member = user;
    return this.commentsRepository.save(comment);
  }

  async findAll(query: FindAllCommentDto) {
    const { page = 1, pageSize = 10, status = 1 } = query;
    // 查询一级评论
    const [topLevelComments, totalCount] = await this.commentsRepository.findAndCount({
      relations: ['member'],
      select: this.findSelect,
      where: { status, parent: 0 }, // 只获取一级评论
      order: { createTime: 'DESC' },
      skip: (page - 1) * pageSize,
      take: pageSize,
    });

    // 对于每一级评论，查询其关联的子评论 每条查3条
    const commentsWithChildren = await Promise.all(
      topLevelComments.map(async (topLevelComment) => {
        const [childComments, totalCount] = await this.commentsRepository.findAndCount({
          relations: ['member'],
          select: this.findSelect,
          where: { parent: topLevelComment.id, status }, // 获取该一级评论下的子评论
          order: { createTime: 'DESC' },
          skip: 0,
          take: 3,
        });

        // 构建完整的评论树结构，将子评论添加到相应的一级评论中
        return {
          ...topLevelComment,
          children: childComments,
          totalCount,
        };
      }),
    );

    return { comments: commentsWithChildren, totalCount };
  }

  async findAllArray(query: FindAllCommentDto) {
    const { page = 1, pageSize = 10, status = 1 } = query;

    const [comments, totalCount] = await this.commentsRepository.findAndCount({
      relations: ['member'],
      select: this.findSelect,
      where: { status },
      order: { createTime: 'DESC' },
      skip: (page - 1) * pageSize,
      take: pageSize,
    });

    return { comments, totalCount };
  }

  async findOne(query: FindOneCommentDto) {
    const { page, pageSize, id } = query;
    const [comments, totalCount] = await this.commentsRepository.findAndCount({
      relations: ['member'],
      select: this.findSelect,
      where: { root: id },
      order: { createTime: 'DESC' },
      skip: (page - 1) * pageSize,
      take: pageSize,
    });
    return { comments, totalCount };
  }

  async update(id: number, updateCommentDto: UpdateCommentDto) {
    const comment = await this.commentsRepository.preload({
      id,
      ...updateCommentDto,
    });
    if (!comment) throw new HttpException(`未找到评论 #${id}`, HttpStatus.NOT_FOUND);
    return this.commentsRepository.save(comment);
  }

  async remove(id: number) {
    const queryRunner = this.connection.createQueryRunner();
    await queryRunner.connect();
    await queryRunner.startTransaction();
    try {
      // 删除id为传入id的评论 和 删除 root为传入id的评论
      await queryRunner.manager.delete(Comment, { id });
      await queryRunner.manager.delete(Comment, { root: id });

      await queryRunner.commitTransaction();
    } catch (error) {
      await queryRunner.rollbackTransaction();
    } finally {
      await queryRunner.release();
    }
  }
}
